//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

/* TVIA 2010 for godson bootloader .
 * We use only 800x600-16 mode for fb driver .
 */

#include <tvia2010.h>   /*IGS I/O and memory header file*/
#include <ddk.h>

ModeInit *IGSModeReg[TOTAL_MODES] =
{
    &Mode_640x480x8_60Hz   ,
    &Mode_640x480x16_60Hz   ,
    &Mode_800x600x16_50Hz  ,
    &Mode_800x600x16_75Hz  ,

};

/*-----------------------------------------------------------------
  NTSC 640x480x60 8/16/24 bpp table
  -----------------------------------------------------------------*/
StandardRegs S640x480x60 = {
    0x00, 0x01, 0x0F, 0x00, 0x0E,       /*Seq Reg<0-4>*/
    0xEF,                               /*Misc Reg */
    0x5F, 0x4F, 0x4F, 0x81, 0x52, 0x9E, 0x0B, 0x3E,
    0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xE9, 0x8B, 0xDF, 0x50, 0x00, 0xE6, 0x04, 0xC3,
    0xFF,                               /*Crtc Reg<0-18>*/
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    0x01, 0x00, 0x0F, 0x00, 0x00,       /*Attr Reg<0-14>*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x05, 0x0F,
    0xFF                                /*Gra  Reg<0-8>*/
};

ExtendedRegs E640x480x8x60 = {      /*8bpp*/
    0x50,                           /*Crtc Reg_13*/
    0xB0, 0xD2,
    0xB1, 0xD3,
    0xBA, 0x00,                     /*Pixel clock overflow register*/
    0x11, 0x00,                     /*ExtRegs*/
    0x14, 0x51,
    0x15, 0x00,
    0x56, 0x00,
    0x77, 0x01
};

ExtendedRegs E640x480x16x60 = {      /*16bpp*/
    {
         0xA0,
         0xB0, 0xD2,
         0xB1, 0xD3,
         0xBA, 0x00,
         0x11, 0x00,
         0x14, 0xA1,
         0x15, 0x00,
         0x56, 0x00,
         0x77, 0x02
    }
};

ModeInit Mode_640x480x8_60Hz = {
    &S640x480x60,
    &E640x480x8x60
};

ModeInit Mode_640x480x16_60Hz = {
     &S640x480x60,
     &E640x480x16x60
};

/*-----------------------------------------------------------------
  PAL 800x600x50 8/16/24 bpp table
  -----------------------------------------------------------------*/
StandardRegs S800x600x50 = {
    0x00, 0x01, 0x0F, 0x00, 0x0E,
    0xEF,
    0x7B, 0x63, 0x64, 0x1C, 0x67, 0x90, 0x6F, 0xF0,
    0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x5C, 0x81, 0x57, 0x64, 0x00, 0x58, 0x6F, 0xE3,
    0xFF,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    0x01, 0x00, 0x0F, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x05, 0x0F,
    0xFF
};

ExtendedRegs E800x600x16x50 = {
    0xC8,
    0xB0, 0x7F,
    0xB1, 0xC8,
    0xBA, 0x1D,
    0x11, 0x00,
    0x14, 0xC9,
    0x15, 0x00,
    0x56, 0x00,
    0x77, 0x02
};

ModeInit Mode_800x600x16_50Hz = {
    &S800x600x50,
    &E800x600x16x50
};

/*-----------------------------------------------------------------
  NORMAL 800x600x75 8/16/24 bpp table
  -----------------------------------------------------------------*/
StandardRegs S800x600x75 = {
    0x00, 0x01, 0x0F, 0x00, 0x0E,
    0xEF,
    0x7F, 0x63, 0x63, 0x01, 0x67, 0x11, 0x6F, 0xF0,
    0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x59, 0x8C, 0x57, 0x64, 0x00, 0x58, 0x6F, 0xE3,
    0xFF,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    0x01, 0x00, 0x0F, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x05, 0x0F,
    0xFF
};

ExtendedRegs E800x600x16x75 = {
    0xC8,
    0xB0, 0x52,
    0xB1, 0x85,
    0xBA, 0x00,
    0x11, 0x00,
    0x14, 0xC9,
    0x15, 0x00,
    0x56, 0x00,
    0x77, 0x02
};

ModeInit Mode_800x600x16_75Hz = {
    &S800x600x75,
    &E800x600x16x75
};

/*------------------------------------------------------------
  This extended register table will initialize the chip into:
  1) 2 MB Video Memory.
  2) 75 Mhz Video Memory Clock.
  3) 640x480x8 @ 60Hz.
  ------------------------------------------------------------*/
BYTE_ ExtRegData[] = {
    /*   index   data   */
    0x10,   0x10,
    0x11,   0x00,
    0x12,   0x00,
    0x14,   0x51,
    0x15,   0x00,
    0x16,   0x00,
    /* reg_30 value will be auto-determined in DetectVideoMemory() */
    0x30,   0x01,  /*0x3CE_30<1,0> = 0x3CE_72<1,0>, Memory size related*/
    0x31,   0x00,
    0x32,   0x00,
    0x3C,   0x00,
    0x3E,   0x00,
    0x3F,   0x00,
    0x50,   0x00,
    0x51,   0x00,
    0x52,   0x00,
    0x53,   0x00,
    0x54,   0x00,
    0x55,   0x00,
    0x56,   0x00,
    0x57,   0x01,
    0x58,   0x00,
    0x59,   0x00,
    0x5A,   0x00,
    0x5C,   0x00,
    0x5D,   0x00,
    0x5E,   0x00,
    0x5F,   0x00,
    0x70,   0x0B,
    0x71,   0x03,
    /* reg_72 value will be auto-determined in DetectVideoMemory() */
#if  1 /* PCI_BUS*/
    0x72,   0x05,     /*2 MB, 64 bits*/
#else /*Non-PCI, such as VL, Motorola, SH3, AMD Elan, etc.*/
    0x72,   0x01,     /*2 MB, 32 bits*/
#endif
    0x73,   0x30,
    0x74,   0x10,
    0x75,   0x10,
    0x76,   0x00,
    0x77,   0x01,     /*8Bpp*/
    0x78,   0x00,
    0x79,   0x33,     /*!!! if Memory Clock < 75 Mhz, 0x79=0x30*/
    0x7A,   0xC8,
    0x90,   0x03,
    0xB0,   0xD2,     /*Pixel Clock = 25.175 MHz*/
    0xB1,   0xD3,
    0xB2,   0xDB,     /*Memory Clock = 75MHz*/
    0xB3,   0x54,
    0xB5,   0x00,
    0xBA,   0x00,
    0xBB,   0x00,
    0xBF,   0x00,
    0xF8,   0x04
};

/*------------------------------------------------------------
  The look up table below will only be needed for 256 color mode
  For 16/24/32 bpp modes, a bypass mode can not enabled (see
  code example)

  Note: value 0x00 is lowest intensity.
  value 0xFF is highest intensity.
  ------------------------------------------------------------*/
BYTE_ RamDacData1[] = {
    /*   Red   Green  Blue  */
  0x00,   0x00,   0x00,
  0x2A,   0x00,   0x00,
  0x00,   0x2A,   0x00,
  0x2A,   0x2A,   0x00,
  0x00,   0x00,   0x2A,
  0x2A,   0x00,   0x2A,
  0x00,   0x15,   0x2A,
  0x2A,   0x2A,   0x2A,
  0x15,   0x15,   0x15,
  0x3F,   0x15,   0x15,
  0x15,   0x3F,   0x15,
  0x3F,   0x3F,   0x15,
  0x15,   0x15,   0x3F,
  0x3F,   0x15,   0x3F,
  0x15,   0x3F,   0x3F,
  0x3F,   0x3F,   0x3F,
  0x00,   0x00,   0x00,
  0x05,   0x05,   0x05,
  0x08,   0x08,   0x08,
  0x0B,   0x0B,   0x0B,
  0x0E,   0x0E,   0x0E,
  0x11,   0x11,   0x11,
  0x14,   0x14,   0x14,
  0x18,   0x18,   0x18,
  0x1C,   0x1C,   0x1C,
  0x20,   0x20,   0x20,
  0x24,   0x24,   0x24,
  0x28,   0x28,   0x28,
  0x2D,   0x2D,   0x2D,
  0x32,   0x32,   0x32,
  0x38,   0x38,   0x38,
  0x3F,   0x3F,   0x3F,
  0x3F,   0x00,   0x00,
  0x3F,   0x00,   0x10,
  0x3F,   0x00,   0x1F,
  0x3F,   0x00,   0x2F,
  0x3F,   0x00,   0x3F,
  0x2F,   0x00,   0x3F,
  0x1F,   0x00,   0x3F,
  0x10,   0x00,   0x3F,
  0x00,   0x00,   0x3F,
  0x00,   0x10,   0x3F,
  0x00,   0x1F,   0x3F,
  0x00,   0x2F,   0x3F,
  0x00,   0x3F,   0x3F,
  0x00,   0x3F,   0x2F,
  0x00,   0x3F,   0x1F,
  0x00,   0x3F,   0x10,
  0x00,   0x3F,   0x00,
  0x10,   0x3F,   0x00,
  0x1F,   0x3F,   0x00,
  0x2F,   0x3F,   0x00,
  0x3F,   0x3F,   0x00,
  0x3F,   0x2F,   0x00,
  0x3F,   0x1F,   0x00,
  0x3F,   0x10,   0x00,
  0x3F,   0x1F,   0x1F,
  0x3F,   0x1F,   0x27,
  0x3F,   0x1F,   0x2F,
  0x3F,   0x1F,   0x37,
  0x3F,   0x1F,   0x3F,
  0x37,   0x1F,   0x3F,
  0x2F,   0x1F,   0x3F,
  0x27,   0x1F,   0x3F,
  0x1F,   0x1F,   0x3F,
  0x1F,   0x27,   0x3F,
  0x1F,   0x2F,   0x3F,
  0x1F,   0x37,   0x3F,
  0x1F,   0x3F,   0x3F,
  0x1F,   0x3F,   0x37,
  0x1F,   0x3F,   0x2F,
  0x1F,   0x3F,   0x27,
  0x1F,   0x3F,   0x1F,
  0x27,   0x3F,   0x1F,
  0x2F,   0x3F,   0x1F,
  0x37,   0x3F,   0x1F,
  0x3F,   0x3F,   0x1F,
  0x3F,   0x37,   0x1F,
  0x3F,   0x2F,   0x1F,
  0x3F,   0x27,   0x1F,
  0x3F,   0x2D,   0x2D,
  0x3F,   0x2D,   0x31,
  0x3F,   0x2D,   0x36,
  0x3F,   0x2D,   0x3A,
  0x3F,   0x2D,   0x3F,
  0x3A,   0x2D,   0x3F,
  0x36,   0x2D,   0x3F,
  0x31,   0x2D,   0x3F,
  0x2D,   0x2D,   0x3F,
  0x2D,   0x31,   0x3F,
  0x2D,   0x36,   0x3F,
  0x2D,   0x3A,   0x3F,
  0x2D,   0x3F,   0x3F,
  0x2D,   0x3F,   0x3A,
  0x2D,   0x3F,   0x36,
  0x2D,   0x3F,   0x31,
  0x2D,   0x3F,   0x2D,
  0x31,   0x3F,   0x2D,
  0x36,   0x3F,   0x2D,
  0x3A,   0x3F,   0x2D,
  0x3F,   0x3F,   0x2D,
  0x3F,   0x3A,   0x2D,
  0x3F,   0x36,   0x2D,
  0x3F,   0x31,   0x2D,
  0x1C,   0x00,   0x00,
  0x1C,   0x00,   0x07,
  0x1C,   0x00,   0x0E,
  0x1C,   0x00,   0x15,
  0x1C,   0x00,   0x1C,
  0x15,   0x00,   0x1C,
  0x0E,   0x00,   0x1C,
  0x07,   0x00,   0x1C,
  0x00,   0x00,   0x1C,
  0x00,   0x07,   0x1C,
  0x00,   0x0E,   0x1C,
  0x00,   0x15,   0x1C,
  0x00,   0x1C,   0x1C,
  0x00,   0x1C,   0x15,
  0x00,   0x1C,   0x0E,
  0x00,   0x1C,   0x07,
  0x00,   0x1C,   0x00,
  0x07,   0x1C,   0x00,
  0x0E,   0x1C,   0x00,
  0x15,   0x1C,   0x00,
  0x1C,   0x1C,   0x00,
  0x1C,   0x15,   0x00,
  0x1C,   0x0E,   0x00,
  0x1C,   0x07,   0x00,
  0x1C,   0x0E,   0x0E,
  0x1C,   0x0E,   0x11,
  0x1C,   0x0E,   0x15,
  0x1C,   0x0E,   0x18,
  0x1C,   0x0E,   0x1C,
  0x18,   0x0E,   0x1C,
  0x15,   0x0E,   0x1C,
  0x11,   0x0E,   0x1C,
  0x0E,   0x0E,   0x1C,
  0x0E,   0x11,   0x1C,
  0x0E,   0x15,   0x1C,
  0x0E,   0x18,   0x1C,
  0x0E,   0x1C,   0x1C,
  0x0E,   0x1C,   0x18,
  0x0E,   0x1C,   0x15,
  0x0E,   0x1C,   0x11,
  0x0E,   0x1C,   0x0E,
  0x11,   0x1C,   0x0E,
  0x15,   0x1C,   0x0E,
  0x18,   0x1C,   0x0E,
  0x1C,   0x1C,   0x0E,
  0x1C,   0x18,   0x0E,
  0x1C,   0x15,   0x0E,
  0x1C,   0x11,   0x0E,
  0x1C,   0x14,   0x14,
  0x1C,   0x14,   0x16,
  0x1C,   0x14,   0x18,
  0x1C,   0x14,   0x1A,
  0x1C,   0x14,   0x1C,
  0x1A,   0x14,   0x1C,
  0x18,   0x14,   0x1C,
  0x16,   0x14,   0x1C,
  0x14,   0x14,   0x1C,
  0x14,   0x16,   0x1C,
  0x14,   0x18,   0x1C,
  0x14,   0x1A,   0x1C,
  0x14,   0x1C,   0x1C,
  0x14,   0x1C,   0x1A,
  0x14,   0x1C,   0x18,
  0x14,   0x1C,   0x16,
  0x14,   0x1C,   0x14,
  0x16,   0x1C,   0x14,
  0x18,   0x1C,   0x14,
  0x1A,   0x1C,   0x14,
  0x1C,   0x1C,   0x14,
  0x1C,   0x1A,   0x14,
  0x1C,   0x18,   0x14,
  0x1C,   0x16,   0x14,
  0x10,   0x00,   0x00,
  0x10,   0x00,   0x04,
  0x10,   0x00,   0x08,
  0x10,   0x00,   0x0C,
  0x10,   0x00,   0x10,
  0x0C,   0x00,   0x10,
  0x08,   0x00,   0x10,
  0x04,   0x00,   0x10,
  0x00,   0x00,   0x10,
  0x00,   0x04,   0x10,
  0x00,   0x08,   0x10,
  0x00,   0x0C,   0x10,
  0x00,   0x10,   0x10,
  0x00,   0x10,   0x0C,
  0x00,   0x10,   0x08,
  0x00,   0x10,   0x04,
  0x00,   0x10,   0x00,
  0x04,   0x10,   0x00,
  0x08,   0x10,   0x00,
  0x0C,   0x10,   0x00,
  0x10,   0x10,   0x00,
  0x10,   0x0C,   0x00,
  0x10,   0x08,   0x00,
  0x10,   0x04,   0x00,
  0x10,   0x08,   0x08,
  0x10,   0x08,   0x0A,
  0x10,   0x08,   0x0C,
  0x10,   0x08,   0x0E,
  0x10,   0x08,   0x10,
  0x0E,   0x08,   0x10,
  0x0C,   0x08,   0x10,
  0x0A,   0x08,   0x10,
  0x08,   0x08,   0x10,
  0x08,   0x0A,   0x10,
  0x08,   0x0C,   0x10,
  0x08,   0x0E,   0x10,
  0x08,   0x10,   0x10,
  0x08,   0x10,   0x0E,
  0x08,   0x10,   0x0C,
  0x08,   0x10,   0x0A,
  0x08,   0x10,   0x08,
  0x0A,   0x10,   0x08,
  0x0C,   0x10,   0x08,
  0x0E,   0x10,   0x08,
  0x10,   0x10,   0x08,
  0x10,   0x0E,   0x08,
  0x10,   0x0C,   0x08,
  0x10,   0x0A,   0x08,
  0x10,   0x0B,   0x0B,
  0x10,   0x0B,   0x0C,
  0x10,   0x0B,   0x0D,
  0x10,   0x0B,   0x0F,
  0x10,   0x0B,   0x10,
  0x0F,   0x0B,   0x10,
  0x0D,   0x0B,   0x10,
  0x0C,   0x0B,   0x10,
  0x0B,   0x0B,   0x10,
  0x0B,   0x0C,   0x10,
  0x0B,   0x0D,   0x10,
  0x0B,   0x0F,   0x10,
  0x0B,   0x10,   0x10,
  0x0B,   0x10,   0x0F,
  0x0B,   0x10,   0x0D,
  0x0B,   0x10,   0x0C,
  0x0B,   0x10,   0x0B,
  0x0C,   0x10,   0x0B,
  0x0D,   0x10,   0x0B,
  0x0F,   0x10,   0x0B,
  0x10,   0x10,   0x0B,
  0x10,   0x0F,   0x0B,
  0x10,   0x0D,   0x0B,
  0x10,   0x0C,   0x0B,
  0x00,   0x00,   0x00,
  0x00,   0x00,   0x00,
  0x00,   0x00,   0x00,
  0x00,   0x00,   0x00,
  0x00,   0x00,   0x00,
  0x00,   0x00,   0x00,
  0x00,   0x00,   0x00,
  0x00,   0x00,   0x00

};
BYTE_ RamDacData[256*3] = {
  /*   Red   Green  Blue  */
       0x00,  0x00,  0x00,
       0x00,  0x00,  0x2A,
       0x00,  0x2A,  0x00,
       0x00,  0x2A,  0x2A,
       0x2A,  0x00,  0x00,
       0x2A,  0x00,  0x2A,
       0x2A,  0x15,  0x00,
       0x2A,  0x2A,  0x2A,
       0x15,  0x15,  0x15,
       0x15,  0x15,  0x3F,
       0x15,  0x3F,  0x15,
       0x15,  0x3F,  0x3F,
       0x3F,  0x15,  0x15,
       0x3F,  0x15,  0x3F,
       0x3F,  0x3F,  0x15,
       0x3F,  0x3F,  0x3F,
       0x00,  0x00,  0x00,
       0x05,  0x05,  0x05,
       0x08,  0x08,  0x08,
       0x0B,  0x0B,  0x0B,
       0x0E,  0x0E,  0x0E,
       0x11,  0x11,  0x11,
       0x14,  0x14,  0x14,
       0x18,  0x18,  0x18,
       0x1C,  0x1C,  0x1C,
       0x20,  0x20,  0x20,
       0x24,  0x24,  0x24,
       0x28,  0x28,  0x28,
       0x2D,  0x2D,  0x2D,
       0x32,  0x32,  0x32,
       0x38,  0x38,  0x38,
       0x3F,  0x3F,  0x3F,
       0x00,  0x00,  0x3F,
       0x10,  0x00,  0x3F,
       0x1F,  0x00,  0x3F,
       0x2F,  0x00,  0x3F,
       0x3F,  0x00,  0x3F,
       0x3F,  0x00,  0x2F,
       0x3F,  0x00,  0x1F,
       0x3F,  0x00,  0x10,
       0x3F,  0x00,  0x00,
       0x3F,  0x10,  0x00,
       0x3F,  0x1F,  0x00,
       0x3F,  0x2F,  0x00,
       0x3F,  0x3F,  0x00,
       0x2F,  0x3F,  0x00,
       0x1F,  0x3F,  0x00,
       0x10,  0x3F,  0x00,
       0x00,  0x3F,  0x00,
       0x00,  0x3F,  0x10,
       0x00,  0x3F,  0x1F,
       0x00,  0x3F,  0x2F,
       0x00,  0x3F,  0x3F,
       0x00,  0x2F,  0x3F,
       0x00,  0x1F,  0x3F,
       0x00,  0x10,  0x3F,
       0x1F,  0x1F,  0x3F,
       0x27,  0x1F,  0x3F,
       0x2F,  0x1F,  0x3F,
       0x37,  0x1F,  0x3F,
       0x3F,  0x1F,  0x3F,
       0x3F,  0x1F,  0x37,
       0x3F,  0x1F,  0x2F,
       0x3F,  0x1F,  0x27,
       0x3F,  0x1F,  0x1F,
       0x3F,  0x27,  0x1F,
       0x3F,  0x2F,  0x1F,
       0x3F,  0x37,  0x1F,
       0x3F,  0x3F,  0x1F,
       0x37,  0x3F,  0x1F,
       0x2F,  0x3F,  0x1F,
       0x27,  0x3F,  0x1F,
       0x1F,  0x3F,  0x1F,
       0x1F,  0x3F,  0x27,
       0x1F,  0x3F,  0x2F,
       0x1F,  0x3F,  0x37,
       0x1F,  0x3F,  0x3F,
       0x1F,  0x37,  0x3F,
       0x1F,  0x2F,  0x3F,
       0x1F,  0x27,  0x3F,
       0x2D,  0x2D,  0x3F,
       0x31,  0x2D,  0x3F,
       0x36,  0x2D,  0x3F,
       0x3A,  0x2D,  0x3F,
       0x3F,  0x2D,  0x3F,
       0x3F,  0x2D,  0x3A,
       0x3F,  0x2D,  0x36,
       0x3F,  0x2D,  0x31,
       0x3F,  0x2D,  0x2D,
       0x3F,  0x31,  0x2D,
       0x3F,  0x36,  0x2D,
       0x3F,  0x3A,  0x2D,
       0x3F,  0x3F,  0x2D,
       0x3A,  0x3F,  0x2D,
       0x36,  0x3F,  0x2D,
       0x31,  0x3F,  0x2D,
       0x2D,  0x3F,  0x2D,
       0x2D,  0x3F,  0x31,
       0x2D,  0x3F,  0x36,
       0x2D,  0x3F,  0x3A,
       0x2D,  0x3F,  0x3F,
       0x2D,  0x3A,  0x3F,
       0x2D,  0x36,  0x3F,
       0x2D,  0x31,  0x3F,
       0x00,  0x00,  0x1C,
       0x07,  0x00,  0x1C,
       0x0E,  0x00,  0x1C,
       0x15,  0x00,  0x1C,
       0x1C,  0x00,  0x1C,
       0x1C,  0x00,  0x15,
       0x1C,  0x00,  0x0E,
       0x1C,  0x00,  0x07,
       0x1C,  0x00,  0x00,
       0x1C,  0x07,  0x00,
       0x1C,  0x0E,  0x00,
       0x1C,  0x15,  0x00,
       0x1C,  0x1C,  0x00,
       0x15,  0x1C,  0x00,
       0x0E,  0x1C,  0x00,
       0x07,  0x1C,  0x00,
       0x00,  0x1C,  0x00,
       0x00,  0x1C,  0x07,
       0x00,  0x1C,  0x0E,
       0x00,  0x1C,  0x15,
       0x00,  0x1C,  0x1C,
       0x00,  0x15,  0x1C,
       0x00,  0x0E,  0x1C,
       0x00,  0x07,  0x1C,
       0x0E,  0x0E,  0x1C,
       0x11,  0x0E,  0x1C,
       0x15,  0x0E,  0x1C,
       0x18,  0x0E,  0x1C,
       0x1C,  0x0E,  0x1C,
       0x1C,  0x0E,  0x18,
       0x1C,  0x0E,  0x15,
       0x1C,  0x0E,  0x11,
       0x1C,  0x0E,  0x0E,
       0x1C,  0x11,  0x0E,
       0x1C,  0x15,  0x0E,
       0x1C,  0x18,  0x0E,
       0x1C,  0x1C,  0x0E,
       0x18,  0x1C,  0x0E,
       0x15,  0x1C,  0x0E,
       0x11,  0x1C,  0x0E,
       0x0E,  0x1C,  0x0E,
       0x0E,  0x1C,  0x11,
       0x0E,  0x1C,  0x15,
       0x0E,  0x1C,  0x18,
       0x0E,  0x1C,  0x1C,
       0x0E,  0x18,  0x1C,
       0x0E,  0x15,  0x1C,
       0x0E,  0x11,  0x1C,
       0x14,  0x14,  0x1C,
       0x16,  0x14,  0x1C,
       0x18,  0x14,  0x1C,
       0x1A,  0x14,  0x1C,
       0x1C,  0x14,  0x1C,
       0x1C,  0x14,  0x1A,
       0x1C,  0x14,  0x18,
       0x1C,  0x14,  0x16,
       0x1C,  0x14,  0x14,
       0x1C,  0x16,  0x14,
       0x1C,  0x18,  0x14,
       0x1C,  0x1A,  0x14,
       0x1C,  0x1C,  0x14,
       0x1A,  0x1C,  0x14,
       0x18,  0x1C,  0x14,
       0x16,  0x1C,  0x14,
       0x14,  0x1C,  0x14,
       0x14,  0x1C,  0x16,
       0x14,  0x1C,  0x18,
       0x14,  0x1C,  0x1A,
       0x14,  0x1C,  0x1C,
       0x14,  0x1A,  0x1C,
       0x14,  0x18,  0x1C,
       0x14,  0x16,  0x1C,
       0x00,  0x00,  0x10,
       0x04,  0x00,  0x10,
       0x08,  0x00,  0x10,
       0x0C,  0x00,  0x10,
       0x10,  0x00,  0x10,
       0x10,  0x00,  0x0C,
       0x10,  0x00,  0x08,
       0x10,  0x00,  0x04,
       0x10,  0x00,  0x00,
       0x10,  0x04,  0x00,
       0x10,  0x08,  0x00,
       0x10,  0x0C,  0x00,
       0x10,  0x10,  0x00,
       0x0C,  0x10,  0x00,
       0x08,  0x10,  0x00,
       0x04,  0x10,  0x00,
       0x00,  0x10,  0x00,
       0x00,  0x10,  0x04,
       0x00,  0x10,  0x08,
       0x00,  0x10,  0x0C,
       0x00,  0x10,  0x10,
       0x00,  0x0C,  0x10,
       0x00,  0x08,  0x10,
       0x00,  0x04,  0x10,
       0x08,  0x08,  0x10,
       0x0A,  0x08,  0x10,
       0x0C,  0x08,  0x10,
       0x0E,  0x08,  0x10,
       0x10,  0x08,  0x10,
       0x10,  0x08,  0x0E,
       0x10,  0x08,  0x0C,
       0x10,  0x08,  0x0A,
       0x10,  0x08,  0x08,
       0x10,  0x0A,  0x08,
       0x10,  0x0C,  0x08,
       0x10,  0x0E,  0x08,
       0x10,  0x10,  0x08,
       0x0E,  0x10,  0x08,
       0x0C,  0x10,  0x08,
       0x0A,  0x10,  0x08,
       0x08,  0x10,  0x08,
       0x08,  0x10,  0x0A,
       0x08,  0x10,  0x0C,
       0x08,  0x10,  0x0E,
       0x08,  0x10,  0x10,
       0x08,  0x0E,  0x10,
       0x08,  0x0C,  0x10,
       0x08,  0x0A,  0x10,
       0x0B,  0x0B,  0x10,
       0x0C,  0x0B,  0x10,
       0x0D,  0x0B,  0x10,
       0x0F,  0x0B,  0x10,
       0x10,  0x0B,  0x10,
       0x10,  0x0B,  0x0F,
       0x10,  0x0B,  0x0D,
       0x10,  0x0B,  0x0C,
       0x10,  0x0B,  0x0B,
       0x10,  0x0C,  0x0B,
       0x10,  0x0D,  0x0B,
       0x10,  0x0F,  0x0B,
       0x10,  0x10,  0x0B,
       0x0F,  0x10,  0x0B,
       0x0D,  0x10,  0x0B,
       0x0C,  0x10,  0x0B,
       0x0B,  0x10,  0x0B,
       0x0B,  0x10,  0x0C,
       0x0B,  0x10,  0x0D,
       0x0B,  0x10,  0x0F,
       0x0B,  0x10,  0x10,
       0x0B,  0x0F,  0x10,
       0x0B,  0x0D,  0x10,
       0x0B,  0x0C,  0x10,
       0x00,  0x00,  0x00,
       0x00,  0x00,  0x00,
       0x00,  0x00,  0x00,
       0x00,  0x00,  0x00,
       0x00,  0x00,  0x00,
       0x00,  0x00,  0x00,
       0x00,  0x00,  0x00,
       0x00,  0x00,  0x00
     };

DWORD_ dwLINEAR_BASE=0; /*virtual address for linear frame buffer*/
DWORD_ dwMEM_IO_BASE=0; /*virtual address for memory mapped I/O*/

/*-------------------------------------------------------------------
 * common function
 *-------------------------------------------------------------------*/

BYTE_ igsinp(WORD_ wPortAddr)
{
    return *((volatile BYTE_ *)(dwMEM_IO_BASE+wPortAddr));
}

void igsoutp(WORD_ wPortAddr, BYTE_ bData)
{
    BYTE_ bTmp;
    bTmp = igsinp(0x3CE);   /*dummy read*/
    *((volatile BYTE_ *)(dwMEM_IO_BASE+wPortAddr)) = bData;
}

void igsoutpw(WORD_ wPortAddr, WORD_ wData)
{
    BYTE_ bTmp;
    bTmp = igsinp(0x3CE);   /*dummy read*/
    *((volatile WORD_ *)(dwMEM_IO_BASE+wPortAddr)) = wData;
}

WORD_ igsinpw(WORD_ wPortAddr)
{
    return *((volatile WORD_ *)(dwMEM_IO_BASE+wPortAddr));
}

void ResetSeq(void)
{
    igsoutp(SEQINDEX,0x00);
    igsoutp(SEQDATA, 0x01);
    igsoutp(SEQINDEX,0x00);
    igsoutp(SEQDATA, 0x03);
}

void ToggleClock(void)
{
    BYTE_ bTmp;

    igsoutp(IGS3CEINDEX, 0xB9);
    bTmp = igsinp(IGS3CFDATA);

    igsoutp(IGS3CFDATA, bTmp & 0x7F);    /*bit <7> is the control bit*/
    igsoutp(IGS3CFDATA, bTmp | 0x80);
    igsoutp(IGS3CFDATA, bTmp & 0x7F);
}

void BypassMode(WORD_ iOnOff)
{
    BYTE_ bTmp;

    igsoutp(IGS3CEINDEX, 0x56);
    bTmp = igsinp(IGS3CFDATA);
    igsoutp(IGS3CFDATA, bTmp | 0x04);

    if (iOnOff == ON)
        igsoutp(RAMDACMASK, igsinp(RAMDACMASK) | 0x10);
    else
        igsoutp(RAMDACMASK, igsinp(RAMDACMASK) & ~0x10);

    igsoutp(IGS3CFDATA, bTmp & ~0x04);
}

extern unsigned char *framebuffer;

extern "C" void SetRamDac(BYTE_ *bPtr, WORD_ iCounter)
{
    WORD_ i;
    igsoutp(RAMDACINDEXW, 0);  /*start from index 0*/

    for (i = 0; i < iCounter; i++) {
        igsoutp(RAMDACDATA, (*bPtr++)); /*R*/
        igsoutp(RAMDACDATA, (*bPtr++)) ; /*G*/
        igsoutp(RAMDACDATA, (*bPtr++));     /*B*/
    }

    igsoutp(RAMDACMASK, 0xff);  /*Mask register*/
}

extern "C" void MySetRamDac(BYTE_ *bPtr, int nIndex)
{
    igsoutp(RAMDACINDEXW, nIndex);  /*start from index 0*/
    igsoutp(RAMDACDATA, *bPtr++); /*R*/
    igsoutp(RAMDACDATA, *bPtr++); /*G*/
    igsoutp(RAMDACDATA, *bPtr++); /*B*/

    igsoutp(RAMDACMASK, 0xff);  /*Mask register*/
}

//extern "C"  int __cdecl kprintf(const char *format, ...);

extern "C" void
MyVideo_WriteDAC(int index, int r, int g, int b)
{
    igsoutp(RAMDACINDEXW, index);
    kprintf("red = %d, green = %d, blue = %d, index = %d\n", r,g, b, index);

    igsoutp(RAMDACMASK, 0xff);

    if (1/*DAC8Bit*/) {
        igsoutp(RAMDACDATA, r<<2);
        igsoutp(RAMDACDATA, g<<2);
        igsoutp(RAMDACDATA, b<<2);
    }
}

WORD_ GetBpp(void)
{
    BYTE_ bModeBpp;

    igsoutp(IGS3CEINDEX, 0x77);
    bModeBpp = igsinp(IGS3CFDATA) & 0x07;

    switch (bModeBpp) {
        case 2:        /*565*/
        case 6:
            bModeBpp = 16;
            break;  /*555*/

        default:
            bModeBpp =  8;
            break;  /*8bpp index*/
    }

    return ((WORD_) bModeBpp);
}

void EnableLinearAddr(void)
{
    igsoutp(IGS3CEINDEX, 0x33);
    igsoutp(IGS3CFDATA, igsinp(IGS3CFDATA) | 0x01);
}

void DisableLinearAddr(void)
{
    igsoutp(IGS3CEINDEX, 0x33);
    igsoutp(IGS3CFDATA, igsinp(IGS3CFDATA) & ~0x01);
}

/*-------------------------------------------------------------------
 * END common function
 *-------------------------------------------------------------------/

/*--------------------------------------------------------------------
  SetStandardReg: Set standard VGA registers
  In: bPtr A BYTE_ pointer to an array of VGA register settings
  Out: VGA registers are set
  --------------------------------------------------------------------*/
void SetStandardReg(BYTE_ *bPtr)
{
    WORD_ i;

    /* 1. set sequencer reg */
    for (i = 0; i < SEQCOUNT; i++) {
        igsoutp(SEQINDEX, (BYTE_) i);
        igsoutp(SEQDATA , *bPtr++);
    }

    /* 2. set miscellaneous reg */
    igsoutp(MISCWRITE, *bPtr++);

    igsoutp(SEQINDEX, 0x00);
    igsoutp(SEQDATA , 0x03);  /*seq normal operation*/

    /* 3. set CRT reg */
    igsoutp(CRTINDEX, 0x11);
    igsoutp(CRTDATA , 0x00);  /*unlock CRT*/

    for (i = 0; i < CRTCOUNT; i++) {
        igsoutp(CRTINDEX, (BYTE_) i);
        igsoutp(CRTDATA , *bPtr++);
    }

    /* 4. set attribute reg */
    i = igsinp(ATTRRESET);  /*reset Attribute*/

    for (i = 0; i < ATTRCOUNT; i++) {
        igsoutp(ATTRINDEX, (BYTE_) i);
        igsoutp(ATTRDATAW, *bPtr++);
    }

    igsoutp(ATTRINDEX, 0x20);  /*turn on screen*/
    i = igsinp(ATTRRESET);  /*reset Attribute*/

    /* 5. set graphics reg */
    for (i = 0; i < GRACOUNT; i++) {
        igsoutp(GRAINDEX, (BYTE_) i);
        igsoutp(GRADATA , *bPtr++);
    }
}

/*--------------------------------------------------------------------
  SetExtReg: Set IGS extended registers
  In: bPtr  A BYTE_ pointer to an array of IGS extended register settings
  iCounter  Counter of the registers.
  Out: Full IGS extended registers are set.
  --------------------------------------------------------------------*/
void SetExtReg(BYTE_ *bPtr, WORD_ iCounter)
{
    WORD_ i;
    for (i = 0; i < iCounter; i++) {
        igsoutp(IGS3CEINDEX, *bPtr++);    /*index*/
        igsoutp(IGS3CFDATA,  *bPtr++);    /*data*/
    }

    ToggleClock();   /*to latch the clock value into working set*/
}

void SetPartExtReg(BYTE_ *bPtr)
{
    WORD_ i;

    igsoutp(CRTINDEX, 0x13);  /*index*/
    igsoutp(CRTDATA ,  *bPtr++); /*data*/

    for (i = 0; i < EXTPARTIALCOUNT; i++) {
        igsoutp(IGS3CEINDEX, *bPtr++);    /*index*/
        igsoutp(IGS3CFDATA,  *bPtr++);    /*data*/
    }

    ToggleClock();   /*to latch the clock value into working set*/
}

/*----------------------------------------------------------------------
  ClearVMem: Clears entire video memory to be 0.
  In: None
  Out: None
  -----------------------------------------------------------------------*/

WORD_ GetVMemSize(void)
{
    BYTE_ bData;
    igsoutp(IGS3CEINDEX, 0x72);
    bData = igsinp(IGS3CFDATA) & 0x03; /*0: 1MB, 1: 2MB, 2: 4MB.*/
    bData <<= 1;
    if (bData == 0)
        bData = 1;
    return (WORD_) bData;
}

void ClearVMem(DWORD_ dwData)
{
    DWORD_    volatile *fpTmp;
    DWORD_ dwMemSize, dwCount;
    
    // /2 to reduce memory clean work
    dwMemSize = 1024 * 1024 / 4 * GetVMemSize() / 2; 

    fpTmp = (DWORD_ *) bpVidMemPtr;

#if 1
    for (dwCount = 0; dwCount < dwMemSize; dwCount++) {
        *fpTmp ++= dwData;
    }
#endif
}

WORD_  TestVMem(WORD_ iBankNum)
{
    WORD_ i,iFlag;
    BYTE_ bData0, bData1;
    BYTE_ bTmp0, bTmp1;

    BYTE_     *fpTmp;

    fpTmp = bpVidMemPtr;
    fpTmp += iBankNum*64*1024;

    iFlag = 0;

    bData0 = 0x55;
    bData1 = 0xAA;
    for (i = 0; i < 16; i++) {
        *fpTmp++ = bData0;
        *fpTmp++ = bData1;
    }

    fpTmp = bpVidMemPtr;

    fpTmp += iBankNum*64*1024;

    for (i = 0; i < 16; i++) {
        bTmp0 = *fpTmp++;
        bTmp1 = *fpTmp++;
        if ((bTmp0 != bData0) || (bTmp1 != bData1))
            iFlag = 1;
    }

    return iFlag;
}

WORD_ DetectVideoMemory(void)
{
    WORD_ i, iFlag;
    BYTE_ bData;

    bData = 0x05;

    /* 1. Detect Video Memory Bus width */

    igsoutp(IGS3CEINDEX, 0x72);
    igsoutp(IGS3CFDATA, bData);
    igsoutp(IGS3CEINDEX, 0x30);
    igsoutp(IGS3CFDATA, bData & 0x03);

    ResetSeq();

    iFlag = 0;
    for (i = 0; i < 32; i++) /*test total 32*64K - 2MB*/ {
        iFlag += TestVMem(i);
    }

    if (iFlag == 0) {
        bData = 0x06;
        igsoutp(IGS3CEINDEX, 0x72);
        /*it is 64 bit. Temporarily force to be 4MB*/
        igsoutp(IGS3CFDATA, bData);
        igsoutp(IGS3CEINDEX, 0x30);
        igsoutp(IGS3CFDATA, bData & 0x03);
    }
    else {
        bData = 0x02;
        igsoutp(IGS3CEINDEX, 0x72);
        /*it is 32 bit. Temporarily force to be 4MB*/
        igsoutp(IGS3CFDATA, bData);
        igsoutp(IGS3CEINDEX, 0x30);
        igsoutp(IGS3CFDATA, bData & 0x03);
    }

    /* 2. Detect Video Memory Size */

    ResetSeq();

    iFlag = 0;
    for (i = 0; i < 64; i++) /*test total 64*64K - 4MB*/ {
        iFlag += TestVMem(i);
    }

    if (iFlag != 0) {
        igsoutp(IGS3CEINDEX, 0x72);
        bData = (igsinp(IGS3CFDATA) & 0xFC) | 0x01;  /*force to be 2MB*/
        igsoutp(IGS3CFDATA, bData);
        igsoutp(IGS3CEINDEX, 0x30);
        igsoutp(IGS3CFDATA, bData & 0x03);

        iFlag = 0;
        for (i = 0; i < 32; i++) /*test total 32*64K - 2MB*/ {
            iFlag += TestVMem(i);
        }

        if (iFlag != 0) {
            bData = 0x00;
            igsoutp(IGS3CEINDEX, 0x72);
            igsoutp(IGS3CFDATA,  bData);/*force to be 1MB/32bits*/
            igsoutp(IGS3CEINDEX, 0x30);
            igsoutp(IGS3CFDATA, bData & 0x03);

            iFlag = 0;
            for (i = 0; i < 16; i++) /*test total 16*64K - 1MB*/ {
                iFlag += TestVMem(i);
            }
        }
    }

    return iFlag;
}

void CleanUpReg(void)
{
    /*
      Unlock CRT
      It is useful only when IGS VGA BIOS is present.
      IGS hardware power on default is CRT unlocked, i.e 3D4_1F default is
      0x03.
    */
    igsoutp(MISCWRITE, igsinp(MISCREAD) | 0x01);
    igsoutp(CRTINDEX, 0x1F);
    igsoutp(CRTDATA,  0x03);     /* to unlock CRT protection */

    /*Underscan registers*/
    igsoutp(CRTINDEX, 0x44);
    igsoutp(CRTDATA,  0x00);
    igsoutp(CRTINDEX, 0x45);
    igsoutp(CRTDATA,  0x00);

    /*Video Capture Registers*/
    igsoutp(IGS3CEINDEX, 0xE8);
    igsoutp(IGS3CFDATA,  0x00);

    /*Video Overlay Registers*/
    igsoutp(IGS3CEINDEX, 0xDC);
    igsoutp(IGS3CFDATA,  0x00);

    igsoutp(IGS3CEINDEX, 0xFA);
    igsoutp(IGS3CFDATA,  0x00);
}

void InitChip(MODEID mode)
{
    ModeInit *bpIGSModeReg;

    SetExtReg(ExtRegData, sizeof(ExtRegData)/2);

    bpIGSModeReg = IGSModeReg[mode];
    SetStandardReg(bpIGSModeReg->bpStdReg->VGARegs);
    SetPartExtReg(bpIGSModeReg->bpExtReg->IGSRegs);
    SetRamDac(RamDacData, sizeof(RamDacData)/3);

    /*choose voltage reference*/
    igsoutp(IGS3CEINDEX, 0x56);
    igsoutp(IGS3CFDATA, 0x04);
    igsoutp(RAMDACMASK, 0x04);   /*use VRef*/
    igsoutp(IGS3CFDATA, 0);
    igsoutp(IGS3CEINDEX, 0x56);
    igsoutp(IGS3CFDATA, 0x00);
}

struct sModeParam sM0 = {(MODEID)0,0,0,0,0};

void EnableChip(char * fbaddress)
{
    //WORD_ iTmp, i;
    DWORD_ dwPhyAddr, dwPhyAddrIO;

    dwPhyAddr   = (unsigned long)fbaddress;
    dwPhyAddrIO = (unsigned long)(fbaddress + 0x00800000);

    dwLINEAR_BASE = dwPhyAddr   | 0xb0000000 ;     /*physical -> linear*/
    dwMEM_IO_BASE = dwPhyAddrIO | 0xb0000000 ;    /*physical -> linear*/
    // eanble chip
    igsoutp(PORT46E8 , 0x18);
    igsoutp(PORT102 ,  0x01);
    igsoutp(PORT46E8 , 0x08);
}

void PostRoutine(MODEID mode)
{
    /*clean up some reigsters in case warm boot*/
    CleanUpReg();

    InitChip(mode);               /* initialize to 640x480x8 @60Hz mode */

    if (DetectVideoMemory() != 0) /* detect video memory size */ {
    /*printf("Something is wrong with Video Memory!!!\n");*/
    }
    ;
}

static void SetDACPower(WORD_ iOnOff)
{
    igsoutp(GRAINDEX,0x56);
    igsoutp(GRADATA,igsinp(GRADATA)|0x04); /*banking bit*/

    if (iOnOff == ON)
        igsoutp(RAMDACMASK,igsinp(RAMDACMASK)&~0x40); /*DAC power on */
    else
        igsoutp(RAMDACMASK, igsinp(RAMDACMASK)|0x40); /*DAC power off*/

    igsoutp(GRAINDEX,0x56);
    igsoutp(GRADATA, igsinp(GRADATA)&~0x04);
}

/*--------------------------------------------------------------------
CleanUpReg: Clean up some registers in case of warm boot
In: None
Out:
--------------------------------------------------------------------*/
void SetIGSMode(struct sModeParam *sM)
{
    ModeInit *bpIGSModeReg;

    bpIGSModeReg = IGSModeReg[sM->wModeID];

    SetDACPower(OFF);

    SetStandardReg(bpIGSModeReg->bpStdReg->VGARegs);
    SetPartExtReg(bpIGSModeReg->bpExtReg->IGSRegs);

    /*turn off pci burst transfer*/
    igsoutp(GRAINDEX,0x30);
    igsoutp(GRADATA,igsinp(GRADATA) & ~ 0xA4);

//    ClearVMem(0x0);

    if (GetBpp() >= 16)
        BypassMode(ON); /*want bypass mode*/
    else { /* only 256 color*/
        BypassMode(OFF);     /*want index mode*/
        SetRamDac(RamDacData, sizeof(RamDacData)/3);
    }

    SetDACPower(ON);
}

//=================================
//  Lighten the LED in ev8172B
//=================================
void led_display(int code)
{
    *((volatile unsigned char *)0xb80000f0) = code & 0x0ff;
}

extern "C" int tvia2010_init(int fbaddress, int ioaddress, MODEID mode)
{
#define TVON   OFF
#define CRTON   ON

#define SCARTTV   OFF
#define PCIBURST  OFF

    sM0.wModeID  = mode;//MODE_800x600x16x75;//MODE_640x480x8x60;   
    sM0.wTVOn  = TVON;
    sM0.wCRTOn  = CRTON;
    sM0.wScartTVOn  = SCARTTV;
    sM0.wPCIBurstOn  = PCIBURST;

    EnableChip((char *)fbaddress);    /*to wake up the chip*/

    PostRoutine(mode);
    ClearVMem(0x0);

    EnableLinearAddr();   /*this routine uses PORT I/O*/

    SetIGSMode(&sM0);

    return 1;
}
